In [1]:
import cv2
import os
import glob
import random
import time
import pickle
import sys
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
import numpy as np
from skimage.feature import hog
from sklearn.svm import LinearSVC
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from scipy.ndimage import label
from moviepy.editor import VideoFileClip
from functools import reduce
%matplotlib inline
In [2]:
# Define a function to return some characteristics of the dataset 

def data_look(car_list, notcar_list):
    data_dict = {}
    # Define a key in data_dict "n_cars" and store the number of car images
    data_dict["n_cars"] = len(car_list)
    # Define a key "n_notcars" and store the number of notcar images
    data_dict["n_notcars"] = len(notcar_list)
    # Read in a test image, either car or notcar
    car_img = mpimg.imread(car_list[0])
    # Define a key "image_shape" and store the test image shape 3-tuple
    data_dict["image_shape"] = car_img.shape
    # Define a key "data_type" and store the data type of the test image.
    data_dict["data_type"] = car_img.dtype
    # Return data_dict
    return data_dict
In [3]:
# Define a function to plot images

def visualize_images(input_images, num_cols, figure_name, cmap = None):
    "Shows input images by stacking them in num_cols columns"
    fig, axes = plt.subplots((int)((len(input_images) + 1) /num_cols), num_cols, figsize=(24, 20))

    fig = plt.gcf()
    fig.canvas.set_window_title(figure_name)
    
    print(figure_name)
    
    for ax, image in zip(axes.flat, input_images):
        if(cmap == "gray" or cmap == 'hot'):
            ax.imshow(image, cmap=cmap)
        elif(image.shape[2]==1):
            ax.imshow(image[:,:,0], cmap = cmap)
        else:
            ax.imshow(image, cmap=cmap)
    plt.show()
In [4]:
#Read cars and not-cars images

#Data folders
vehicles_dir = './data/vehicles/'
non_vehicles_dir = './data/non-vehicles/'

# images are divided up into vehicles and non-vehicles
cars = []
notcars = []

# Read vehicle images
images = glob.iglob(vehicles_dir + '/**/*.png', recursive=True)

for image in images:
        cars.append(image)
        
# Read non-vehicle images
images = glob.iglob(non_vehicles_dir + '/**/*.png', recursive=True)

for image in images:
        notcars.append(image)
    
data_info = data_look(cars, notcars)

print('Your function returned a count of', data_info["n_cars"], ' cars and', data_info["n_notcars"], ' non-cars')
print('of size: ',data_info["image_shape"], ' and data type:', data_info["data_type"])
Your function returned a count of 8792  cars and 8968  non-cars
of size:  (64, 64, 3)  and data type: float32
In [5]:
# ### Visualize sample images for car and not car types


#Visualize some input images

num_images = 10

# Just for fun choose random car / not-car indices and plot example images   
cars_samples = random.sample(list(cars), num_images)
notcar_samples = random.sample(list(notcars), num_images)
    
# Read in car / not-car images
car_images = []
notcar_images = []
for sample in cars_samples:
    car_images.append(mpimg.imread(sample))
    
for sample in notcar_samples:
    notcar_images.append(mpimg.imread(sample))
visualize_images(car_images, num_images, "Example Car images")
Example Car images
In [6]:
visualize_images(notcar_images, num_images, "Example not-car images")
Example not-car images
In [7]:
#Helper functions for transforming the images to generate more images

def translate_image(image, pos_range=2):
    """Perturbs the image by translating the image by - pos_range to + pos_range pixels"""
    rows, cols = image.shape[:2] 
    pos_x = pos_range * np.random.uniform() - pos_range/2
    pos_y = pos_range * np.random.uniform() - pos_range/2
    pos_M = np.float32([[1, 0, pos_x],[0, 1, pos_y]])

    return cv2.warpAffine(image, pos_M, (cols,rows))

def scale_image(image, scale = [1.0, 1.1, 1.2]):
    """Perturbs the image by the scale randomly selected from the 'scale' array"""
    scale_M = random.sample(scale, 1)[0]
    image = cv2.resize(image, None, fx = scale_M, fy = scale_M, interpolation = cv2.INTER_AREA)
    return image[0:64, 0:64, :]

def rotate_image(image, rot_range = 2):
    """Perturbs the image by rotation it by an angle randomly selected from rot_rangle"""
    rows, cols = image.shape[:2] 
    rot = np.random.uniform(rot_range)- rot_range/2
    rot_M = cv2.getRotationMatrix2D((cols/2, rows/2), rot, 1)
    
    return cv2.warpAffine(image, rot_M, (cols,rows))

def affine_image(image, affine_range = 2):
    #Affine Transform
    rows, cols = image.shape[:2] 
    pts1 = np.float32([[5, 5],[10, 5],[5, 10]])

    pt1 = 5 + affine_range * np.random.uniform() - affine_range/2
    pt2 = 10 + affine_range * np.random.uniform() - affine_range/2

    pts2 = np.float32([[pt1, 5],[pt2, pt1],[5, pt2]])

    affine_M = cv2.getAffineTransform(pts1, pts2)
    return cv2.warpAffine(image, affine_M, (cols,rows))

def transform_image(image, pos_range = 2, rot_range = 2, scale = [1, 1.1], affine_range = 2):    
    image = translate_image(image, pos_range=5) 
    image = rotate_image(image, rot_range = 5)
    image = scale_image(image, scale = [1.2, 1.4, 1.0])
    is_blurred = random.sample([0, 1], 1)
    if is_blurred[0]:
        image = cv2.GaussianBlur(image,(3,3),0)

    return image
In [8]:
# ### Select and visualize various color spaces


def convert_color(img, conv='RGB2YCrCb'):
    """
    Convert the image from one color space to the other
    """
    if conv == 'RGB2YCrCb':
        return cv2.cvtColor(img, cv2.COLOR_RGB2YCrCb)
    if conv == 'BGR2YCrCb':
        return cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
    if conv == 'RGB2LUV':
        return cv2.cvtColor(img, cv2.COLOR_RGB2LUV)
    if conv == 'RGB2HLS':
        return cv2.cvtColor(img, cv2.COLOR_RGB2HLS)
    if conv == 'RGB2HSV':
        return cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
    if conv == 'Gray':
        return cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
    if conv == 'RGB2YUV':
        return cv2.cvtColor(img, cv2.COLOR_RGB2YUV)
    if conv == 'BGR2RGB':
        return cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
In [9]:
# # Plot the YUV example

def plot_YUV():
    fig = plt.figure()
    plt.subplot(141)
    yuv_image = convert_color(car_images[1], 'RGB2YUV')
    plt.imshow(yuv_image[:,:,0], cmap ="gray")
    plt.title('Y channel')
    plt.subplot(142)
    plt.imshow(yuv_image[:,:,1], cmap ="gray")
    plt.title('U Channel')
    plt.subplot(143)
    plt.imshow(yuv_image[:,:,2], cmap ="gray")
    plt.title('V Channel')
    plt.subplot(144)
    plt.imshow(yuv_image)
    plt.title('YUV')
    
plot_YUV()
In [10]:
# ### Select and visualize required train features (HOG and color features)

def get_hog_features(img, orient, pix_per_cell, cell_per_block, vis=False, feature_vec=True):
    """
    Return the hog features of the given input image
    Call with two outputs if vis==True"""
    if vis == True:
        features, hog_image = hog(img, orientations=orient, pixels_per_cell=(pix_per_cell, pix_per_cell), cells_per_block=(cell_per_block, cell_per_block), transform_sqrt=True, visualize=vis, feature_vector=feature_vec)
        return features, hog_image
    # Otherwise call with one output
    else:      
        features = hog(img, orientations=orient, pixels_per_cell=(pix_per_cell, pix_per_cell), cells_per_block=(cell_per_block, cell_per_block), transform_sqrt=True, visualize=vis, feature_vector=feature_vec)
        return features
In [11]:
# # Plot the HOG example

def plot_HOG(debugMode = False):
    orient = 9
    pix_per_cell = 8
    cell_per_block = 2

    car_features, hog_image = get_hog_features(cv2.cvtColor(car_images[1], cv2.COLOR_RGB2GRAY), orient, pix_per_cell, cell_per_block, vis=True, feature_vec=True)

    notcar_features, notcar_hog_image = get_hog_features(cv2.cvtColor(notcar_images[2], cv2.COLOR_RGB2GRAY), orient, pix_per_cell, cell_per_block, vis=True, feature_vec=True)

    # Plot the examples
    fig = plt.figure()
    plt.subplot(131)
    plt.imshow(car_images[1])
    plt.title('Example Car Image')
    plt.subplot(132)
    plt.imshow(hog_image, cmap='gray')
    plt.title('car HOG Visualization')
    plt.subplot(133)
    plt.imshow(notcar_hog_image, cmap='gray')
    plt.title('not car HOG Visualization')
    
plot_HOG()
    
def bin_spatial(img, size=(16, 16)):
    color1 = cv2.resize(img[:,:,0], size).ravel()
    color2 = cv2.resize(img[:,:,1], size).ravel()
    color3 = cv2.resize(img[:,:,2], size).ravel()
    return np.hstack((color1, color2, color3))
In [12]:
# Define a function to compute color histogram features 

def color_hist(img, nbins=32, bins_range=(0, 256)):
    # Compute the histogram of the color channels separately
    channel1_hist = np.histogram(img[:,:,0], bins=nbins, range=bins_range)
    channel2_hist = np.histogram(img[:,:,1], bins=nbins, range=bins_range)
    channel3_hist = np.histogram(img[:,:,2], bins=nbins, range=bins_range)
    # Concatenate the histograms into a single feature vector
    hist_features = np.concatenate((channel1_hist[0], channel2_hist[0], channel3_hist[0]))
    # Return the individual histograms, bin_centers and feature vector
    return hist_features
In [13]:
# Define a function to extract features from a list of images
# Have this function call bin_spatial() and color_hist()

def extract_features(imgs, cspace='RGB', spatial_size=(32, 32), hist_bins=32, orient=9, pix_per_cell=8, cell_per_block=2, hog_channel='ALL', spatial_feat=False, hist_feat=False, hog_feat=True):
    # Create a list to append feature vectors to
    features = []
    # Iterate through the list of images
    for file in imgs:
        file_features = []
        # Read in each one by one
        image = mpimg.imread(file)
        image = (image * 255).astype(np.uint8)
        # apply color conversion if other than 'RGB'
        if cspace != 'RGB':
            if cspace == 'HSV':
                feature_image = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)
            elif cspace == 'LUV':
                feature_image = cv2.cvtColor(image, cv2.COLOR_RGB2LUV)
            elif cspace == 'HLS':
                feature_image = cv2.cvtColor(image, cv2.COLOR_RGB2HLS)
            elif cspace == 'YUV':
                feature_image = cv2.cvtColor(image, cv2.COLOR_RGB2YUV)
            elif cspace == 'YCrCb':
                feature_image = cv2.cvtColor(image, cv2.COLOR_RGB2YCrCb)
        else: feature_image = np.copy(image)      

        if spatial_feat == True:
            spatial_features = bin_spatial(feature_image, size=spatial_size)
            file_features.append(spatial_features)
        if hist_feat == True:
            # Apply color_hist()
            hist_features = color_hist(feature_image, nbins=hist_bins)
            file_features.append(hist_features)
        if hog_feat == True:
        # Call get_hog_features() with vis=False, feature_vec=True
            hog_features = []
            for channel in range(feature_image.shape[2]):
                hog_features.append(get_hog_features(feature_image[:,:,channel], orient, pix_per_cell, cell_per_block, vis=False, feature_vec=True))
            hog_features = np.ravel(hog_features)   

            # Append the new feature vector to the features list
            file_features.append(hog_features)
        features.append(np.concatenate(file_features))
    # Return list of feature vectors
    return features
In [14]:
# ### Train the classifier on the features



# ### Steps for running the models of the test images
# a. Do a sliding window search with different window scales tp detect bounding boxes  
# b. Merge the bounding boxes using heat maps and thresholding  
# c. Display bounding boxes on the images  



# Define a single function that can extract features using hog sub-sampling and make predictions

def find_cars(img, ystart, ystop, scale, svc, X_scaler, orient, pix_per_cell, cell_per_block, spatial_size, hist_bins, vis_bboxes = False):
    
    draw_img = np.copy(img)
    xstart = int(img.shape[1]/5)
    xstop = img.shape[1]
    img_tosearch = img[ystart:ystop, xstart:xstop,:]
    ctrans_tosearch = convert_color(img_tosearch, conv='RGB2YUV')
    if scale != 1:
        imshape = ctrans_tosearch.shape
        ctrans_tosearch = cv2.resize(ctrans_tosearch, (np.int(imshape[1]/scale), np.int(imshape[0]/scale)))

    ch1 = ctrans_tosearch[:,:,0]
    ch2 = ctrans_tosearch[:,:,1]
    ch3 = ctrans_tosearch[:,:,2]

    # Define blocks and steps as above
    nxblocks = (ch1.shape[1] // pix_per_cell) - cell_per_block + 1
    nyblocks = (ch1.shape[0] // pix_per_cell) - cell_per_block + 1 
    nfeat_per_block = orient*cell_per_block**2
    
    # 64 was the orginal sampling rate, with 8 cells and 8 pix per cell
    window = 64
    nblocks_per_window = (window // pix_per_cell) - cell_per_block + 1
    cells_per_step = 2  # Instead of overlap, define how many cells to step
    nxsteps = (nxblocks - nblocks_per_window) // cells_per_step
    nysteps = (nyblocks - nblocks_per_window) // cells_per_step

    # Compute individual channel HOG features for the entire image
    hog1 = get_hog_features(ch1, orient, pix_per_cell, cell_per_block, feature_vec=False)
    hog2 = get_hog_features(ch2, orient, pix_per_cell, cell_per_block, feature_vec=False)
    hog3 = get_hog_features(ch3, orient, pix_per_cell, cell_per_block, feature_vec=False)
    rectangles = []

    for xb in range(nxsteps):
        for yb in range(nysteps):
            ypos = yb*cells_per_step
            xpos = xb*cells_per_step
            
            # Extract HOG for this patch
            
            hog_feat1 = hog1[ypos:ypos+nblocks_per_window, xpos:xpos+nblocks_per_window].ravel() 
            hog_feat2 = hog2[ypos:ypos+nblocks_per_window, xpos:xpos+nblocks_per_window].ravel() 
            hog_feat3 = hog3[ypos:ypos+nblocks_per_window, xpos:xpos+nblocks_per_window].ravel() 
            hog_features = np.hstack((hog_feat1, hog_feat2, hog_feat3)).reshape(1, -1)         
            xleft = xpos*pix_per_cell
            ytop = ypos*pix_per_cell
 
             # Get color features
            test_features = X_scaler.transform(hog_features)   
            test_prediction = svc.predict(test_features)
            if test_prediction == 1 or vis_bboxes == True:
                xbox_left = np.int(xleft*scale)
                ytop_draw = np.int(ytop*scale)
                win_draw = np.int(window*scale)
                rectangles.append(((xbox_left+xstart, ytop_draw+ystart),(xbox_left+win_draw+xstart,ytop_draw+win_draw+ystart)))
                              
    return rectangles
In [15]:
# Define a function to get the rectangles positions 

def get_rectangles(image, scales = [1, 1.5, 2, 2.5, 3], ystarts = [400, 400, 450, 450, 460], ystops = [528, 550, 620, 650, 700]):
    out_rectangles = []
    for scale, ystart, ystop in zip(scales, ystarts, ystops):
        rectangles = find_cars(image, ystart, ystop, scale, svc, X_scaler, orient, pix_per_cell, cell_per_block, spatial_size, hist_bins)
        if len(rectangles) > 0:
            out_rectangles.append(rectangles)
    out_rectangles = [item for sublist in out_rectangles for item in sublist] 
    return out_rectangles
In [16]:
def add_heat(heatmap, bbox_list):
    # Iterate through list of bboxes
    for box in bbox_list:
        # Add += 1 for all pixels inside each bbox
        # Assuming each "box" takes the form ((x1, y1), (x2, y2))
        heatmap[box[0][1]:box[1][1], box[0][0]:box[1][0]] += 1

    # Return updated heatmap
    return heatmap
In [17]:
# Define a function to get heatmap of the cars

def add_heat(heatmap, bbox_list):
    # Iterate through list of bboxes
    for box in bbox_list:
        # Add += 1 for all pixels inside each bbox
        # Assuming each "box" takes the form ((x1, y1), (x2, y2))
        heatmap[box[0][1]:box[1][1], box[0][0]:box[1][0]] += 1

    # Return updated heatmap
    return heatmap
In [18]:
# Define a function to apply thresholding

def apply_threshold(heatmap, threshold):
    # Zero out pixels below the threshold
    heatmap[heatmap <= threshold] = 0
    # Return thresholded map
    return heatmap
In [19]:
# Define a function to generate the output image

def draw_labeled_bboxes(img, labels):
    # Iterate through all detected cars
    img_copy = np.copy(img)
    result_rectangles = []
    for car_number in range(1, labels[1]+1):
        # Find pixels with each car_number label value
        nonzero = (labels[0] == car_number).nonzero()
        # Identify x and y values of those pixels
        nonzeroy = np.array(nonzero[0])
        nonzerox = np.array(nonzero[1])
        # Define a bounding box based on min/max x and y
        bbox = ((np.min(nonzerox), np.min(nonzeroy)), (np.max(nonzerox), np.max(nonzeroy)))
        area = (bbox[1][1] - bbox[0][1]) * (bbox[1][0] - bbox[0][0])
        if area > 40 * 40:
            result_rectangles.append(bbox)
            # Draw the box on the image
            cv2.rectangle(img_copy, bbox[0], bbox[1], (0,255,0), 6)
    # Return the image
    return result_rectangles, img_copy
In [20]:
# Define a function to draw the boxes

def draw_boxes(img, bboxes, color=(0, 0, 255), thick=6):
    # Make a copy of the image
    imcopy = np.copy(img)
    random_color = False
    # Iterate through the bounding boxes
    for bbox in bboxes:
        if color == 'random' or random_color:
            color = (np.random.randint(0,255), np.random.randint(0,255), np.random.randint(0,255))
            random_color = True
        # Draw a rectangle given bbox coordinates
        cv2.rectangle(imcopy, bbox[0], bbox[1], color, thick)
    # Return the image copy with boxes drawn
    return imcopy
In [21]:
# Define a function to visualize boxes

def visualize_bboxes(image, scales = [1, 1.5, 2, 2.5, 3], ystarts = [400, 400, 450, 450, 460], ystops = [528, 550, 620, 650, 700]):
    out_rectangles = []
    for scale, ystart, ystop in zip(scales, ystarts, ystops):
        rectangles = find_cars(image, ystart, ystop, scale, svc, X_scaler, orient, pix_per_cell, cell_per_block, spatial_size, hist_bins, vis_bboxes = True)
        if len(rectangles) > 0:
            out_rectangles.append(rectangles)
    out_rectangles = [item for sublist in out_rectangles for item in sublist] 

    plt.figure(figsize=(20,10))
    plt.imshow(draw_boxes(image, out_rectangles, color='random', thick=3))
In [22]:
colorspace = 'YUV' # Can be RGB, HSV, LUV, HLS, YUV, YCrCb
orient = 9
pix_per_cell = 8
cell_per_block = 2
hog_channel = 'ALL' # Can be 0, 1, 2, or "ALL"
spatial_size=(32, 32)
hist_bins=32
t=time.time()
car_features = extract_features(cars, cspace=colorspace, orient=orient, pix_per_cell=pix_per_cell, cell_per_block=cell_per_block, hog_channel=hog_channel, hist_bins=hist_bins)
notcar_features = extract_features(notcars, cspace=colorspace, orient=orient, pix_per_cell=pix_per_cell, cell_per_block=cell_per_block, hog_channel=hog_channel, hist_bins=hist_bins)
t2 = time.time()
print(round(t2-t, 2), 'Seconds to extract HOG features...')

# Create an array stack of feature vectors
X = np.vstack((car_features, notcar_features)).astype(np.float64) 
print(X.shape)
# Fit a per-column scaler

X_scaler = StandardScaler().fit(X)

# Apply the scaler to X
scaled_X = X_scaler.transform(X)

# Define the labels vector
y = np.hstack((np.ones(len(car_features)), np.zeros(len(notcar_features))))

print(len(y))

# Split up data into randomized training and test sets
rand_state = np.random.randint(0, 100)
X_train, X_test, y_train, y_test = train_test_split(scaled_X, y, test_size=0.15, random_state=rand_state)
print('Using:',orient,'orientations',pix_per_cell, 'pixels per cell and', cell_per_block,'cells per block')
print('Feature vector length:', len(X_train[0]))

# Use a linear SVC X_scaler
svc = LinearSVC()
# Check the training time for the SVC
t=time.time()
svc.fit(X_train, y_train)
t2 = time.time()
print(round(t2-t, 2), 'Seconds to train SVC...')

# Check the score of the SVC
print('Test Accuracy of SVC = ', round(svc.score(X_test, y_test), 4))

# Check the prediction time for a single sample
t=time.time()
n_predict = 10
print('My SVC predicts: ', svc.predict(X_test[0:n_predict]))
print('For these',n_predict, 'labels: ', y_test[0:n_predict])
t2 = time.time()
print(round(t2-t, 5), 'Seconds to predict', n_predict,'labels with SVC')


# #### Save the training model 


#Pickle the data as it takes a lot of time to generate it

data_file = './results/model/svc_pickle.p'

if not os.path.isfile(data_file):
    with open(data_file, 'wb') as pfile:
        pickle.dump(
            {
                'svc': svc,
                'scaler': X_scaler,
                'orient': orient,
                'pix_per_cell': pix_per_cell,
                'cell_per_block': cell_per_block,
                'spatial_size': spatial_size,
                'hist_bins': hist_bins
                
            },
            pfile, pickle.HIGHEST_PROTOCOL)

print('Data saved in pickle file')
252.81 Seconds to extract HOG features...
(17760, 5292)
17760
Using: 9 orientations 8 pixels per cell and 2 cells per block
Feature vector length: 5292
14.2 Seconds to train SVC...
Test Accuracy of SVC =  0.9872
My SVC predicts:  [1. 1. 1. 0. 1. 1. 1. 1. 0. 1.]
For these 10 labels:  [1. 1. 1. 0. 1. 1. 1. 1. 0. 1.]
0.01204 Seconds to predict 10 labels with SVC
Data saved in pickle file
In [23]:
## Step 2: Detect vehicles on the test images

#### Load the test images
# path of the image directory or the video file 
inputFilepath="./data/test_images/"
# path where the output file will be saved
outputFilepath="./results/output_images/"
# Type of the file (image or video)
fileType="image"

if (fileType == 'image'):
# images are divided up into vehicles and non-vehicles
    test_images = []
    images = glob.glob(inputFilepath + '*.jpg')

    print("img", images)
    for image in images:
        test_images.append(mpimg.imread(image))

    print(test_images)
    


    result_images = []
    result_boxes = []
    heatmap_images = []
    result_img_all_boxes = []
    for test_image in test_images:
        rectangles = get_rectangles(test_image)
        result_img_all_boxes.append(draw_boxes(test_image, rectangles, color='random', thick=3))
        heatmap_image = np.zeros_like(test_image[:, :, 0])
        heatmap_image = add_heat(heatmap_image, rectangles)
        heatmap_images.append(heatmap_image)
        heatmap_image = apply_threshold(heatmap_image, 2)
        labels = label(heatmap_image)
        rectangles, result_image = draw_labeled_bboxes(test_image, labels)
        result_boxes.append(rectangles)
        result_images.append(result_image)

    for index, img in enumerate(result_images):
        cv2.imwrite(outputFilepath + str(index + 1) + '.jpg', convert_color(img, conv='BGR2RGB'))
img ['./data/test_images\\test1.jpg', './data/test_images\\test2.jpg', './data/test_images\\test3.jpg', './data/test_images\\test4.jpg', './data/test_images\\test5.jpg', './data/test_images\\test6.jpg']
[array([[[245, 235, 226],
        [242, 238, 235],
        [193, 206, 215],
        ...,
        [ 11,  36,  58],
        [ 16,  38,  59],
        [ 28,  49,  70]],

       [[242, 238, 235],
        [188, 193, 196],
        [139, 158, 173],
        ...,
        [ 74, 108, 135],
        [ 47,  77, 105],
        [  4,  34,  60]],

       [[190, 203, 212],
        [135, 157, 171],
        [118, 153, 181],
        ...,
        [ 96, 144, 182],
        [ 91, 136, 175],
        [ 52,  97, 136]],

       ...,

       [[142, 131, 129],
        [132, 121, 117],
        [114, 100,  97],
        ...,
        [ 99,  80,  74],
        [ 99,  80,  74],
        [113,  94,  88]],

       [[164, 154, 152],
        [133, 122, 118],
        [120, 106, 103],
        ...,
        [107,  88,  82],
        [109,  90,  84],
        [111,  92,  86]],

       [[189, 179, 177],
        [135, 126, 121],
        [130, 116, 113],
        ...,
        [ 97,  78,  72],
        [ 95,  76,  70],
        [ 73,  54,  48]]], dtype=uint8), array([[[246, 242, 243],
        [211, 210, 215],
        [179, 183, 192],
        ...,
        [ 21,  37,  52],
        [ 36,  44,  57],
        [ 41,  47,  59]],

       [[196, 199, 208],
        [146, 153, 163],
        [129, 142, 158],
        ...,
        [ 45,  66,  87],
        [ 18,  33,  52],
        [ 29,  42,  59]],

       [[136, 154, 176],
        [134, 156, 180],
        [108, 135, 162],
        ...,
        [ 86, 119, 154],
        [ 50,  79, 111],
        [ 11,  36,  67]],

       ...,

       [[128, 114, 105],
        [ 94,  80,  71],
        [ 94,  80,  71],
        ...,
        [ 88,  71,  64],
        [ 91,  74,  67],
        [132, 115, 108]],

       [[132, 119, 111],
        [101,  88,  80],
        [ 93,  79,  70],
        ...,
        [ 89,  74,  69],
        [104,  89,  84],
        [135, 120, 115]],

       [[145, 132, 124],
        [126, 113, 105],
        [103,  89,  80],
        ...,
        [ 73,  58,  53],
        [122, 107, 102],
        [147, 132, 127]]], dtype=uint8), array([[[182, 202, 211],
        [136, 158, 171],
        [125, 151, 168],
        ...,
        [ 31,  72, 100],
        [  1,  35,  60],
        [ 17,  49,  70]],

       [[138, 160, 173],
        [136, 159, 173],
        [131, 158, 179],
        ...,
        [ 88, 131, 163],
        [ 54,  91, 117],
        [  0,  35,  59]],

       [[129, 155, 172],
        [134, 161, 182],
        [121, 149, 173],
        ...,
        [ 96, 142, 176],
        [ 90, 133, 165],
        [ 32,  73, 101]],

       ...,

       [[131, 116, 111],
        [105,  90,  85],
        [100,  82,  78],
        ...,
        [ 78,  67,  65],
        [ 91,  80,  78],
        [129, 118, 116]],

       [[147, 133, 130],
        [125, 111, 108],
        [105,  90,  87],
        ...,
        [ 84,  73,  71],
        [119, 108, 106],
        [144, 134, 132]],

       [[155, 141, 138],
        [122, 108, 105],
        [113,  98,  95],
        ...,
        [123, 112, 110],
        [142, 132, 130],
        [190, 180, 178]]], dtype=uint8), array([[[ 45,  58,  67],
        [ 33,  47,  58],
        [ 30,  46,  61],
        ...,
        [175, 184, 191],
        [211, 212, 216],
        [242, 242, 242]],

       [[ 29,  47,  61],
        [ 21,  40,  55],
        [ 62,  83, 102],
        ...,
        [137, 153, 168],
        [154, 164, 173],
        [189, 198, 205]],

       [[ 11,  41,  65],
        [ 75, 105, 131],
        [127, 158, 186],
        ...,
        [125, 155, 181],
        [132, 158, 181],
        [134, 159, 179]],

       ...,

       [[ 76,  65,  63],
        [ 99,  88,  86],
        [100,  89,  87],
        ...,
        [ 94,  77,  70],
        [106,  89,  82],
        [142, 125, 118]],

       [[ 65,  55,  54],
        [103,  93,  92],
        [107,  95,  95],
        ...,
        [ 82,  64,  60],
        [ 99,  84,  79],
        [133, 118, 113]],

       [[ 34,  24,  23],
        [ 78,  68,  67],
        [112, 100, 100],
        ...,
        [ 75,  57,  53],
        [116, 101,  96],
        [149, 134, 129]]], dtype=uint8), array([[[ 48,  54,  70],
        [ 38,  45,  55],
        [ 34,  38,  41],
        ...,
        [ 74,  95,  80],
        [102, 118, 105],
        [143, 160, 144]],

       [[ 40,  46,  60],
        [ 29,  33,  42],
        [ 20,  24,  23],
        ...,
        [  9,  27,  15],
        [ 21,  37,  24],
        [ 88, 105,  89]],

       [[ 35,  42,  50],
        [ 23,  28,  32],
        [ 18,  23,  17],
        ...,
        [ 19,  37,  25],
        [  7,  23,  10],
        [ 14,  28,  15]],

       ...,

       [[ 34,  35,  39],
        [ 51,  51,  53],
        [ 97,  88,  91],
        ...,
        [121, 106, 103],
        [121, 106, 103],
        [124, 109, 106]],

       [[ 43,  46,  51],
        [ 30,  29,  34],
        [ 68,  59,  64],
        ...,
        [130, 115, 112],
        [131, 116, 113],
        [135, 120, 117]],

       [[ 48,  51,  56],
        [ 37,  36,  41],
        [ 37,  31,  35],
        ...,
        [137, 122, 119],
        [138, 123, 120],
        [141, 126, 123]]], dtype=uint8), array([[[246, 233, 224],
        [237, 232, 228],
        [195, 204, 213],
        ...,
        [ 14,  36,  57],
        [ 18,  39,  58],
        [ 23,  44,  63]],

       [[239, 231, 228],
        [186, 186, 188],
        [138, 151, 167],
        ...,
        [ 80, 107, 134],
        [ 53,  81, 105],
        [  7,  35,  59]],

       [[197, 201, 212],
        [138, 150, 166],
        [129, 155, 182],
        ...,
        [101, 140, 179],
        [ 96, 136, 172],
        [ 55,  95, 131]],

       ...,

       [[ 70,  57,  51],
        [110,  97,  89],
        [107,  90,  83],
        ...,
        [ 95,  75,  66],
        [ 98,  78,  69],
        [102,  82,  73]],

       [[103,  90,  84],
        [ 82,  69,  61],
        [ 99,  82,  75],
        ...,
        [ 81,  61,  52],
        [ 89,  69,  60],
        [111,  91,  82]],

       [[172, 159, 153],
        [ 70,  57,  49],
        [121, 104,  97],
        ...,
        [ 77,  57,  48],
        [ 88,  68,  59],
        [114,  94,  85]]], dtype=uint8)]
In [24]:
visualize_bboxes(test_images[0])
In [25]:
visualize_images(result_img_all_boxes, 2, "test")
test
In [26]:
visualize_images(result_images, 2, "Car detection")
Car detection
In [27]:
visualize_images(heatmap_images, 2, "Heatmap", cmap="hot")
Heatmap
In [28]:
# ## Video Processing

if (fileType == "video"):
    class HeatHistory():
        def __init__(self):
            self.history = []

    def processVideo(inputVideo, outputVideo, frames_to_remember=3, threshhold=1):
        """
        Process the video `inputVideo` to find the cars and saves the video to `outputVideo`.
        """
        history = HeatHistory()

        def pipeline(img):
            boxes = get_rectangles(img)
            img_shape = img.shape
            heatmap = add_heat(np.zeros(img_shape), boxes)
            if len(history.history) >= frames_to_remember:
                history.history = history.history[1:]

            history.history.append(heatmap)
            heat_history = reduce(lambda h, acc: h + acc, history.history)/frames_to_remember
            heatmap = apply_threshold(heat_history, threshhold)
            labels = label(heatmap)

            return draw_labeled_bboxes(np.copy(img), labels)[1]

        myclip = VideoFileClip(inputVideo)
        output_video = myclip.fl_image(pipeline)
        output_video.write_videofile(outputVideo, audio=False)

    processVideo(inputFilepath, outputFilepath + "output.mp4", threshhold=2)

    os.startfile(outputFilepath + "output.mp4")